home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / graphics / artpacks / acid0896 / xbin.tut < prev    next >
Text File  |  1996-07-31  |  31KB  |  612 lines

  1.  
  2.  
  3.                        eXtended BIN programming tutorial
  4.                       -----------------------------------
  5.  
  6.                    Written by Tasmanic Tasmaniac / ACiD 1996
  7.                      No rights reserved, No patent pending
  8.                      For comments/questions : Tas@acid.org
  9.                    http://uc2.unicall.be/tasmaniac/xbin.htm
  10.  
  11.  
  12.  
  13.   Introduction
  14.   -------------
  15.  
  16.   XBIN offers many features several coders have never programmed before.
  17.   For this reason, I'll cover these aspects of text mode programming within
  18.   this small tutorial.
  19.  
  20.   An understanding of assembly is required.  Source code is provided in
  21.   assembly.  The reason for the choice is obvious, most of the code involves
  22.   dealing with VGA registers and bit twiddling, two things assembly is the
  23.   best choice for.
  24.  
  25.   I'll be covering most of the features at a novice to moderate programming
  26.   level.  In case you don't understand some parts, it may be a good idea to
  27.   grab a couple of books on VGA programming.  This text is by no means the
  28.   ultimate reference for the VGA.  Some exceptions excluded, I'l usually be
  29.   describing HOW the overall concept works, and not enter into details on
  30.   how the VGA hardware actually works, you'll need to consult a decent
  31.   reference for that.
  32.  
  33.   NOTE ! Assembly sequences assume that any register may be freely modified
  34.   Depending on language used this is not the case (Pascal requires you to
  35.   restore SS, SP, BP & DS to their original values upon leaving the Assembly
  36.   code.  Most C compilers require that on top of those four registers, you
  37.   also keep SI and DI intact).  Check the manual of your compiler for
  38.   specifics.  Most compilers allow for inline assembly code, this way it
  39.   should be fairly easy to use the features described here.
  40.  
  41.   The code samples are for VGA ONLY (!) do NOT use them on a EGA, most
  42.   codesamples won't work on EGA.  The code only modifies what it needs to
  43.   perform it's job, when only one bit needs to be modified, the others are
  44.   preserved.
  45.  
  46.   Please note: I did not have a chance to test all of the code on it's
  47.   workings, most of it is taken directly out of the XBIN viewer, so should
  48.   be functional, if you use the source listed HERE however, some minor
  49.   mistakes may have slipped in.
  50.  
  51.   The XBIN Viewer should be a fairly good reference on how to implement a
  52.   basic XBIN viewer.
  53.  
  54.  
  55.   VGA in general
  56.   ---------------
  57.  
  58.   The VGA usually behaves as a pretty simple device.  Textmode and 256 color
  59.   graphics modes are easy to work with.  The VGA BIOS usually offers enough
  60.   functionality to make use of most of what the VGA has to offer.
  61.   Unfortunately the VGA BIOS is also notoriously slow.  Especially when
  62.   writing a protected mode program, using the BIOS often to perform simple
  63.   operations can literrally slow your program to a crawl.
  64.  
  65.   In such cases, or when the BIOS simple doesn't cut the cake, you will have
  66.   to program the VGA directly.  This is usually where the mess starts.
  67.  
  68.   While this small tutorial is far from a complete reference for the VGA, it
  69.   should be more than adequate when you want to make full use of the XBIN
  70.   format.  All the sample code is functional.  If you REALLY want to know
  71.   what exactly is going on, then you should consult a VGA reference.
  72.  
  73.   Some good books I have read myself and recommend to anyone involved in
  74.   graphics and/or demo programming :
  75.     Programmer's Guide to the EGA & VGA Cards by R. Ferraro (Addison-Wesley)
  76.       This book is one of the most complete VGA references available.  It is
  77.       currently in it's third print, and involves everything from EGA, to
  78.       VGA, to SVGA and even covers the most commonly used SVGA accelerator
  79.       chips.  Even though it lacks sample code to explain most of what it
  80.       covers, it remains something to have lying beside you when coding
  81.       graphics.
  82.     Zen of graphics programming by Michael Abrash (Coriolis group books)
  83.       A very easy to read book covering most of the aspects of the VGA
  84.       hardware, textmode, 16 color graphics, 256 color, and tweaked mode.
  85.       You'll also find some pretty fast code for lines, polygons, circles,
  86.       sprites and so on.  It even has a complete 3D library included.
  87.       It's a book I strongly recommend to anyone who needs a little push in
  88.       the back to get going with graphics.  The sample code is usually
  89.       listed in a simple C version, and then goes to several fases of
  90.       optimisation (ending up with ASM)
  91.     PC & PS/2 video systems by Richard Wilton (Microsoft Press)
  92.       UGH! Am I actually advertising something by Microsoft...  Ah well...
  93.       Like Zen of Graphics programming, this book also covers most of the
  94.       aspects of the video hardware.  This book does however also cover MGA,
  95.       CGA, Hercules, Hercules plus, EGA, MCGA and VGA.  Because everything
  96.       but the VGA have become near extinct, you may end up using only a
  97.       small portion of the book.  The sample code (Basic, Pascal, C & ASM)
  98.       however is usually of pretty good quality.
  99.  
  100.   Enough about books, let's get on with the show.
  101.  
  102.   On top of that, we'll also cover decrunching and crunching an XBIN file,
  103.   and even touch the aspect of on-the-fly-decrunching.
  104.  
  105.  
  106.   Setting the VGA palette in text mode
  107.   -------------------------------------
  108.  
  109.   This is one of the features most of the programmers know pretty well, and
  110.   indeed, in 256 color graphics, where this feature is used most, it's pretty
  111.   simple to do.  Each pixel color nicely translates to a palette Red, Green,
  112.   Blue value.
  113.   In textmode, things are slightly more complicated.  In order to be
  114.   compatible with the EGA, in textmode the 16color EGA palette is used. The
  115.   EGA palette then maps into the 256 color VGA palette to find the RGB values
  116.   to send to the monitor.
  117.   Unfortunately, the 16 color EGA palette does NOT map to the first 16 colors
  118.   of the VGA palette.  Fortunately though, we CAN program the EGA palette to
  119.   do just that.
  120.   Setting the 16 color RGB palette stored in an XBIN takes two steps.
  121.    - Set the EGA palette to map to the first 16 colors of the VGA palette
  122.    - Set the first 16 RGB values in the VGA palette.
  123.  
  124.               MOV    DX,003DAh         ; CRTC Status register
  125.               IN     AL,DX             ; Read CRTC Status.  (This will reset
  126.                                        ; the Attribute controller flip-flop)
  127.             ; Set EGA palette to color 0-15
  128.               MOV    DX,003C0h         ; Attribute controller
  129.               MOV    AL,0              ; Color 0. (and Clears PAS field)
  130.     NxtPalEGA:OUT    DX,AL             ; Set paletteregister to change
  131.               OUT    DX,AL             ; Set value for palette register
  132.               INC    AL                ; Next color
  133.               CMP    AL,0Fh            ; All colors done ?
  134.               JBE    NxtPalEGA         ; Nope.
  135.               MOV    AL,20h
  136.               OUT    DX,AL             ; Set PAS field (Video has access to
  137.                                        ; palette)
  138.  
  139.               ; set VGA palette 0-15 to black
  140.               MOV    DX,003C8h         ; VGA Palette Address Register
  141.               MOV    AL,0              ; Set palette starting with color 0
  142.               OUT    DX,AL             ; Set color 0.
  143.               INC    DX                ; DX=003C9 (VGA Palette Data register)
  144.  
  145.               PUSH   DS                ; Save DS
  146.               MOV    SI,Seg XBIN.PAL   ; Segment of XBIN Palette in SI
  147.               MOV    DS,SI             ; And copy in DS
  148.               MOV    SI,Offset XBIN.PAL; Offset of XBIN Palette in SI
  149.               MOV    CX,3*16           ; 16 times 3 values (Red, Green Blue)
  150.               CLD                      ; Increment with LODS/STOS/MOVS
  151.     NxtPalVGA:LODSB                    ; Load byte at DS:SI, increment SI
  152.               OUT    DX,AL             ; Set R, G or B value.
  153.               LOOP   NxtPalVGA         ; Loop for all 16*3 values.
  154.               POP    DS                ; Restore DS
  155.  
  156.  
  157.   Setting the VGA in (non-)Blink mode
  158.   ------------------------------------
  159.  
  160.   When in blink-mode, the highest bit of the attribute byte determines
  161.   whether the character will blink or not.  In nonblink-mode this same bit
  162.   selects high-intensity colors.  Note however that 'high-intensity' does not
  163.   really apply to XBIN, since all of the 16 colors can be redefined.
  164.   In any case, it's a matter of choosing between 16 background colors, or 8
  165.   background colors plus blinking.
  166.  
  167.   Setting blink or nonblink mode is pretty easy really, all that needs to be
  168.   done is set or clear a single bit in the 'Mode Control' register.
  169.  
  170.   Enabling (default) blink mode.
  171.  
  172.               MOV    DX,003DAh         ; CRTC Status register
  173.               IN     AL,DX             ; Read CRTC Status.  (This will reset
  174.                                        ; the Attribute controller flip-flop)
  175.               ; Set blink bit
  176.               MOV    DX,003C0h         ; Attribute controller (Write port)
  177.               MOV    AL,10h+20h        ; Register 10h (Mode control)
  178.                                        ; leave PAS field enabled.
  179.               OUT    DX,AL             ; Activate register 10h
  180.               INC    DX                ; DX=003C1h (Attribute READ port)
  181.               IN     AL,DX             ; Read Mode control register
  182.               DEC    DX                ; DX=003C0h (Attribute Write port)
  183.               OR     AL,008h           ; Set blink bit
  184.               OUT    DX,AL             ; Rewrite Mode control register
  185.  
  186.  
  187.  
  188.   Disabling blink mode.
  189.  
  190.               MOV    DX,003DAh         ; CRTC Status register
  191.               IN     AL,DX             ; Read CRTC Status.  (This will reset
  192.                                        ; the Attribute controller flip-flop)
  193.               ; Set blink bit
  194.               MOV    DX,003C0h         ; Attribute controller (Write port)
  195.               MOV    AL,10h+20h        ; Register 10h (Mode control)
  196.                                        ; leave PAS field enabled.
  197.               OUT    DX,AL             ; Activate register 10h
  198.               INC    DX                ; DX=003C1h (Attribute READ port)
  199.               IN     AL,DX             ; Read Mode control register
  200.               DEC    DX                ; DX=003C0h (Attribute Write port)
  201.               AND    AL,NOT 008h       ; Clear blink bit
  202.               OUT    DX,AL             ; Rewrite Mode control register
  203.  
  204.   ! NOTE ! When running in Windows in windowed mode, whatever you try you
  205.   ALWAYS have nonblink mode.  Switching back and forth between full-screen
  206.   mode and windowed mode, can have effect on the blink/nonblink status.
  207.   In case you're wondering... it's just one of the shitload of bugs in
  208.   Windows.
  209.  
  210.  
  211.   Setting the VGA in 512 Character mode
  212.   --------------------------------------
  213.  
  214.   When in 512 character mode, bit 3 of the attribute byte selects which of
  215.   the two character sets to use.  This does mean of course that you can only
  216.   have a maximum of 8 foreground colors.
  217.   It would be VERY tedious to draw an image in 512 character mode without a
  218.   program to support it, and this is probably the reason why this feature is
  219.   almost never used.  Then again, it could be quite usefull for certain
  220.   applications.  Since there is no 'predefined' set of characters for the
  221.   extra set of characters, you could use it to have special 'pictures' and
  222.   'icons' in textmode without it ever interfering with the actual 256
  223.   character ASCII set.
  224.  
  225.   Setting up the VGA in 512 character mode is pretty easy.  The "character
  226.   map select" register holds which two out of 8 possible loaded character sets
  227.   you want to select.  When both the values for character set A, and
  228.   character set B are identical, 256 character mode is selected, when they
  229.   differ, 512 character mode is selected... Gee, THAT's easy ain't it ? :-)
  230.  
  231.   Since we basically want to have the easiest way to have it appear to have
  232.   one continuous set of 512 characters, all we need to do is program the
  233.   Character Map Select register so we have the first 256 characters in the
  234.   TOP 8Kb of font memory, and the second 256 characters in the NEXT 8K of
  235.   font memory.  To do this we must set Character set A to 0, and Character
  236.   set B to 4, the reason for this 0 and 4, in stead of the more logical 0
  237.   and 1 is to provide compatibility with the EGA.
  238.  
  239.   Enabling 512 character mode
  240.  
  241.               MOV    DX,003C4h         ; Sequencer register
  242.               MOV    AX,01003h         ; Character Map Select in AL (index 3)
  243.                                        ; And setup for 4 in SBH field and 0
  244.                                        ; in SAH field loaded in AH
  245.               OUT    DX,AX             ; And write Value.
  246.  
  247.   Disabling 512 character mode (enabling 256 character mode)
  248.  
  249.               MOV    DX,003C4h         ; Sequencer register
  250.               MOV    AX,00003h         ; Character Map Select in AL (index 3)
  251.                                        ; And setup for 0 in SBH field and 0
  252.                                        ; in SAH field loaded in AH
  253.               OUT    DX,AX             ; And write Value.
  254.  
  255.   Simple eh ?  All that's left now is to actually load the font, and setting
  256.   font size.  We'll come to that part shortly.
  257.  
  258.  
  259.   Blinking and 512 Characters
  260.   ----------------------------
  261.  
  262.   As a reminder.  The attribute byte is set up as follows
  263.  
  264.                      7    6   5   4     3     2   1   0
  265.                   ┌─────┬───┬───┬───╥───────┬───┬───┬───┐
  266.                   │ B/I │ R │ G │ B ║ 512/I │ R │ G │ B │
  267.                   └─────┴───┴───┴───╨───────┴───┴───┴───┘
  268.  
  269.   Bit 0: Blue foreground
  270.   Bit 1: Green foreground
  271.   Bit 2: Red foreground
  272.   Bit 3: Intensity bit in 256 character mode and/or
  273.          Select 1st or 2nd 256 of characters of a 512 character set
  274.   Bit 4: Blue background
  275.   Bit 5: Green background
  276.   Bit 6: Red background
  277.   Bit 7: Blinking or
  278.          Intensity
  279.  
  280.   Please note, the R, G, and B values are assuming the DEFAULT palette, when
  281.   you reprogram the palette there is really no longer any Red, Green and
  282.   Blue value as described here.  Heck, you could have ONLY shades of red for
  283.   all that matter.
  284.   In the same way, the 'Intensity' not necesarrily means 'Brighter' color.
  285.   Setting up color value 4 to blue, and color value 12 ('Intensity' color 4)
  286.   to green, would have it blinking between blue and green.
  287.  
  288.   When 512 character mode is enabled, Bit 3 determines both which of the two
  289.   256 character sets to use AND the intensity bit.  This can lead to confusing
  290.   results in a XBIN drawing package.  A simple way to work around this is to
  291.   program the palette so that the first and last eight palette values are
  292.   identical.
  293.  
  294.  
  295.   Setting font size.
  296.   ------------------
  297.  
  298.   The default VGA text mode is a 720*400 pixel mode.  Each character is made
  299.   up of a matrix of 8 pixels wide and 16 pixels high.  Something strange
  300.   happens here.  When IBM developped the VGA, one of it's intensions was to
  301.   provide a more readable and 'nicer' looking character set compared to the
  302.   EGA which utilized a 8*14 font.  The main problem however was not having a
  303.   character matrix with more lines, but a character matrix with more
  304.   columns, since a PC typically works with BYTES however, it'd be pretty
  305.   hard to organize a system whith for example 9, 10 or 11 bits per scanline.
  306.   So they adopted for the system already widely in use on the Hercules card.
  307.   The Hercules provided a better character by having 9 pixels per font row,
  308.   however, NO extra bit was needed.  As it turns out, the only problem is
  309.   the small space in between to adjacent characters... Why not utilize
  310.   8 bits from a byte to have an 8 pixel wide actual font, and insert a blank
  311.   pixel so there's some space...  And this is exactly how it works.  There
  312.   are a few exceptions though, the box drawing characters (╚═─│┤╢...) would
  313.   look messy if they were separated by one pixel so for those characters,
  314.   the eigth column is doubled.
  315.   There is NO way to select which of the 256/512 characters should have a
  316.   blank column or column 8 doubled, the set of characters with this doubling
  317.   is fixed they are 0C0h to 0DFh (192 to 223).  You CAN however switch the
  318.   VGA into 640*400 mode, so it utilises an 8 pixel wide font.  This does
  319.   reduce the quality of the characters slightly, but this usually not a bad
  320.   thing, and ANSi's tend to look prettier in 640*400. ;-)
  321.  
  322.   Switching the VGA into 8 pixel mode involves some pretty messy bit
  323.   twiddling.  You should generally set 8 pixelmode immediately after setting
  324.   the videomode.  This code WILL most likely cause the screen to flicker. On
  325.   a multisyncing or variable scanning rate monitor, it will cause the
  326.   monitor to go blank for a short period of time while the monitor adjusts
  327.   to the new scanning rate.  It will generally cause the same sort of
  328.   flicker/disturbance as when you switch from textmode to graphics and/or
  329.   back.  Since the setting a video mode will probably already do the same,
  330.   it will cause the least amount of disturbance right after a mode set.
  331.   I'm not providing any code for switching back from 8 to 9 pixel font, I
  332.   recommend switching back to textmode using BIOS interrupt 10, function 0,
  333.   set mode.  If you really need code to switch back to 9 pixel mode, you
  334.   will need to derive the appropriate method from the following code.
  335.  
  336.   Setting 640 pixel wide screen (and a 8 pixel wide characterbox).
  337.  
  338.               MOV    DX,003CCh         ; Misc output register READ port
  339.               IN     AL,DX             ; Read value.
  340.               AND    AL,0F3h           ; Turn off Bits 2 & 3 (Clock select 0).
  341.               MOV    DX,003C2h         ; Misc Output Write port
  342.               OUT    DX,AL             ; Writeback modified value
  343.  
  344.               CLI                      ; NO interrupts for a while
  345.               MOV    DX,03C4h          ; Sequencer register
  346.               MOV    AX,100h           ; \ Generate and hold Synchronous reset
  347.               OUT    DX,AX             ; /
  348.  
  349.               MOV    AL,001h           ; Clocking mode register
  350.               OUT    DX,AL             ; Activate Clocking mode register
  351.               INC    DX                ; Data register
  352.               IN     AL,DX             ; Read value
  353.               OR     AL,1              ; Set Bit 0 (8/9)
  354.               OUT    DX,AL             ; Writeback.
  355.               DEC    DX                ; Back to Address register
  356.  
  357.               MOV    AX,300h           ; \ Release Reset state. (normal)
  358.               OUT    DX,AX             ; /
  359.               STI                      ; Interrupts allowed again
  360.  
  361.   Even though the VGA allows to have 6, 8, 12 and 16 pixel wide actual
  362.   fonts, I'm not going to go any further on that here, XBIN only supports 8
  363.   pixel wide fonts anyway.
  364.  
  365.   XBIN does allow for setting any font HEIGHT from 1 to 32 however, so we
  366.   need to be able to set that.  As it turns out, this too is pretty simple,
  367.   all we need to do it set the "Maximum Scanline Register" to the number of
  368.   required scanlines minus one,
  369.  
  370.               MOV    DX,003D4h         ; CRTC address register
  371.               MOV    AL,9              ; Index for Maximum Scanline Register
  372.               OUT    DX,AL             ; set MSL as active register
  373.               INC    DX                ; Set DX to CRTC Data register
  374.               IN     AL,DX             ; read current MSL
  375.               AND    AL,011100000b     ; set MSL field to 0, preserve others
  376.               MOV    AH,XBIN.Fontsize  ; get required size from XBIN header
  377.               DEC    AH                ; minus one.
  378.               OR     AL,AH             ; set size in MSL field
  379.               OUT    DX,AL             ; Writeback modified value
  380.  
  381.  
  382.   Setting a characterset (font)
  383.   ------------------------------
  384.  
  385.   The VGA allows you to load up to 8 fonts into fontmemory, and then using
  386.   the Character Map Select register, select which of the eight you currently
  387.   want to use.  There's too much to tell about all the possibilities here,
  388.   so we'll focus on the possible needs by XBIN.
  389.  
  390.   When in textmode, the VGA really works in a pretty odd way.  The memory is
  391.   organised into four planes just as with 16 color graphics.  Character
  392.   bytes reside on plane 0, attribute bytes reside on plane 1, and the font
  393.   is available in plane three.  To provide compatibility with CGA & EGA,
  394.   planes 0 and 1 are also mapped in the B800h address space.  It's a little
  395.   off topic to try to explain all of it, heck it takes an entire chapter in
  396.   most VGA reference books again, we'll focus only on the needs by XBIN.
  397.  
  398.   In the way the Character Map Select was setup earlier, all we need to do
  399.   is load a 256 character font into the first 8Kb of fontmemory, or a 512
  400.   character font into the first 16Kb of font memory.
  401.  
  402.   Because of the character/attribute mapping to 0B800h, the video memory is
  403.   no longer available as a linear set of memory.  Setting a font will
  404.   consist of three major blocks.
  405.  
  406.   A) Initialize the VGA for reading/writing font data
  407.      - Setting the memory to "Sequential" addressing mode
  408.      - Select memory plane 2 for read and write access
  409.      - Disable odd addressing mode
  410.      - Select 0A000h as memory range in stead of 0B800h
  411.  
  412.   B) Actually loading the font
  413.  
  414.   C) Restoring the VGA to it's state prior to step A)
  415.      - Setting memory to "Odd/Even" addressing mode
  416.      - Select plane 0 and 1 for write access
  417.      - Select plane 0 for read access
  418.      - Enable odd addressing mode
  419.  
  420.   Steps A) and C) involve accessing VGA registers,  B) is really pretty
  421.   straightforward, and merely consists of copying the font data into font
  422.   memory in the appropriate format required by the VGA (more on this in a
  423.   moment).
  424.  
  425.   On to some code....
  426.  
  427.   - Initialize the VGA for reading/writing font data
  428.  
  429.               CLI                 ; No interrupts allowed
  430.               MOV    DX,003C4h    ; Sequencer register
  431.               MOV    AX,0100h     ; ┬> Synchronous reset
  432.               OUT    DX,AX        ; ┘
  433.               MOV    AX,0402h     ; ┬> Select Plane 2 for WRITE
  434.               OUT    DX,AX        ; ┘
  435.               MOV    AX,0704h     ; ┬> Sequential Addressing mode
  436.               OUT    DX,AX        ; ┘
  437.               MOV    AX,0300h     ; ┬> Release Synchronous reset
  438.               OUT    DX,AX        ; ┘
  439.  
  440.               MOV    DX,003CEh    ; Graphics controller register
  441.               MOV    AX,0204h     ; ┬> Select Plane 2 for READ
  442.               OUT    DX,AX        ; ┘
  443.               MOV    AX,0005h     ; ┬> Disable odd addressing mode
  444.               OUT    DX,AX        ; ┘
  445.               MOV    AX,0006h     ; ┬> Memory range is A000:0000
  446.               OUT    DX,AX        ; ┘
  447.               STI                 ; Interrupts enabled
  448.  
  449.  
  450.   - Restoring the VGA to it's state prior to step A)
  451.  
  452.               CLI                 ; No interrupts allowed.
  453.               MOV    DX,003C4     ; Sequence controller register
  454.               MOV    AX,0100h     ; ┬> Synchronous reset
  455.               OUT    DX,AX        ; ┘
  456.               MOV    AX,0302h     ; ┬> Select Plane 0 & 1 for WRITE
  457.               OUT    DX,AX        ; ┘
  458.               MOV    AX,0304h     ; ┬> Odd/Even Addressing mode
  459.               OUT    DX,AX        ; ┘
  460.               MOV    AX,0300h     ; ┬> Release Synchronous reset
  461.               OUT    DX,AX        ; ┘
  462.  
  463.               MOV    DX,003CEh    ; Graphics controller register
  464.               MOV    AX,0004h     ; ┬> Select Plane 0 for READ
  465.               OUT    DX,AX        ; ┘
  466.               MOV    AX,1005h     ; ┬> Enable odd addressing mode
  467.               OUT    DX,AX        ; ┘
  468.               MOV    AX,0E06h     ; ┬> Memory range is B800:0000
  469.               OUT    DX,AX        ; ┘
  470.               STI                 ; Interrupts enabled
  471.  
  472.   - Loading a font
  473.  
  474.   Fontmemory is organised in an array of 256 (or 512) character matrices.
  475.   Each matrix is exactly 32bytes in size.  a 256 character font thus
  476.   occupies 8Kb of memory, nomatter what the 'height' of the font.  An XBIN
  477.   font however does not enforce this 32bytes size.  While the VGA had a
  478.   speed consideration, XBIN has a size consideration, it would waste too
  479.   much size.  It's easily done to convert the XBIN format to VGA format, all
  480.   that needs to be don is insert some gaps in between each character.  The
  481.   following does just that.
  482.  
  483.  
  484.               PUSH   DS
  485.               MOV    DI,0A000h
  486.               MOV    ES,DI
  487.               XOR    DI,DI        ; ES:DI points to screen font (A000:000)
  488.  
  489.               LDS    SI,[FontData]; DS:SI points to font data
  490.               MOV    BX,256       ; (or 512) number of characters
  491.               MOV    AX,[CharSize]; Size of character
  492.  
  493.               CLD                 ; Increment pointers on MOVSB, STOSB...
  494.               MOV    DX,32        ; ┬> DX has 32-CharSize (Size of gap in
  495.               SUB    DX,AX        ; ┘  between two screen memory characters
  496.   NextChar:   MOV    CX,AX        ; CX=FontHeight
  497.               REP    MOVSB        ; Copy 'FontHeight' bytes to videomemory
  498.               ADD    DI,DX        ; Skip to next character (leave a gap)
  499.               DEC    BX           ; One character done.
  500.               JNZ    @NextChar
  501.               POP    DS
  502.  
  503.  
  504.   Decompressing an XBIN
  505.   ----------------------
  506.  
  507.   Decompressing an XBIN is pretty straightforward.  First you would need to
  508.   allocate an array of the required size, and then decompress the XBIN data
  509.   into the array.  Depending on how rugged you want to make it, checks for
  510.   invalid XBIN files are needed.  Then again, you could just depend on the
  511.   XBIN on being without error, and have your program crash when it's not ;-)
  512.  
  513.   The decompression process is very simple.  Load a counter/compression type
  514.   byte and depending on the compression type decode the correct number of
  515.   bytes.
  516.  
  517.   A rough outline (no error checks).  For size reasons, I've deliberately
  518.   not used REAL usable code, It should be fairly easy to create that
  519.   yourself.  An actual working routine is available in the SIMPLEXB viewer.
  520.  
  521.   WHILE Still_bytes_in_XBIN
  522.      Counter := Character_from_XBIN
  523.      Type    := Counter & 0C0h         ; Mask out bits 6 and 7
  524.      Counter := Counter & 03Fh         ; Remore 'Type' bits from Counter.
  525.  
  526.      IF (Type = 000h) THEN             ; No compression
  527.         FOR i:=1 TO Counter+1
  528.            Character := Character_from_XBIN
  529.            Attribute := Character_from_XBIN
  530.            Store_In_Array (Character, Attribute)
  531.         ENDFOR
  532.      ELSEIF (TYPE = 040h) THEN         ; Character compression
  533.         Character := Character_from_XBIN
  534.         FOR i:=1 TO Counter+1
  535.            Attribute := Character_from_XBIN
  536.            Store_In_Array (Character, Attribute)
  537.         ENDFOR
  538.      ELSEIF (TYPE = 080h) THEN         ; Attribute compression
  539.         Attribute := Character_from_XBIN
  540.         FOR i:=1 TO Counter+1
  541.            Character := Character_from_XBIN
  542.            Store_In_Array (Character, Attribute)
  543.         ENDFOR
  544.      ELSE                              ; Character/Attribute compression
  545.         Character := Character_from_XBIN
  546.         Attribute := Character_from_XBIN
  547.         FOR i:=1 TO Counter+1
  548.            Store_In_Array (Character, Attribute)
  549.         ENDFOR
  550.      ENDIF
  551.   ENDWHILE
  552.  
  553.  
  554.   On-the-fly (realtime) decompression
  555.   ------------------------------------
  556.  
  557.   In stead of decompressing an entire XBIN, and then use the decompressed
  558.   data to display the XBIN, you could create a system where you only
  559.   decompress the part of the XBIN you actually need.  While being more
  560.   complex, it DOES allow for a more memory efficient viewer capable of
  561.   viewing XBIN files substantially larger than available memory.
  562.  
  563.   While not impossible, it'd probably be too difficult to create an
  564.   ANSi/XBIN editor making full use of this possibility.
  565.  
  566.   The provided viewer SIMPLEXB.EXE/SIMPLEXB.PAS uses this method, making it
  567.   possible to view XBIN files of any size (even of 65535 by 65535 in size !)
  568.   Note that this DOES make the viewer slower, since it continuously needs to
  569.   load portions of the XBIN from disk.  Better ways for having realtime
  570.   compression are possible, it would make the SIMPLE viewer too COMPLEX
  571.   however ;-).
  572.  
  573.  
  574.   Compressing an XBIN
  575.   --------------------
  576.  
  577.   This is somewhat harder to explain...  While it looks easy at first, it
  578.   takes quite a bit of work to create an XBIN compressor that achieves good
  579.   to perfect compression.  The Sample BIN2XBIN program, includes a complete
  580.   and near-perfect compression algorythm.
  581.  
  582.   As a test case I've also created an optimal XBIN compressor that makes the
  583.   smallest possible XBIN, it is however considerable more complex, a
  584.   magnitude slower and consumes a massive amount more memory than the
  585.   provided BIN2XBIN program.  For those interested in numbers... This
  586.   compressor is made in 32-Bit C enabling to use arrays of any size within
  587.   available memory, The compressor has roughly 7 times as many lines of
  588.   code, consumes up to 4Mb of memory on a 160characters wide XBIN, and
  589.   executes about 30 times slower as BIN2XBIN on a 80characters wide XBIN,
  590.   and 100times slower on a 160characters wide XBIN.  It basically tests all
  591.   possible compression types at each character, reverting to the smallest
  592.   size it found in the process.
  593.  
  594.   Several tests on compressing the ANSi's in a dozen or so art packs from the
  595.   last few months indicated the compression algorythm in BIN2XBIN provides
  596.   very good compression at very little memory and time cost.  None of the
  597.   ANSi's I tried (which I converted to BIN first) resulted in a XBIN that
  598.   was bigger as it's BIN.  It is however possible to create a
  599.   worst-case situation, in which the BIN2XBIN consitently makes the wrong
  600.   decisions resulting in a file being 33.33% bigger than the optimal
  601.   compressed one.  Luckily, those ANSi's tend to be very unattractive by
  602.   nature.
  603.  
  604.   I've spent quite a while thinking about how to implement a fast, yet
  605.   simple and efficient XBIN compressor. Nevertheless, nobody is perfect.  If
  606.   you do find an algorythm that consistently provides better compression
  607.   than BIN2XBIN I would like to hear from you.
  608.  
  609.   Actual code is available in BIN2XBIN.PAS.
  610.  
  611.                                  -THE-END-
  612. SAUCE00eXtended BIN programming tutorial  Tasmaniac           ACiD Productions    19960801xPc